[bits 32]

;这么处理的目的是为了保持对其使处理函数简单，无需对没有错误码的单独处理。
; 对于CPU会自动压入错误码的中断类型，无需额外的操作
%define ERROR_CODE nop
; 如果CPU没有压入错误码，为了保持处理逻辑的一致性，我们需要手动压入一个0
%define ZERO push 0
extern idt_table

section .data
global intr_entry_table
intr_entry_table:

; 中断处理程序宏定义
%macro VECTOR 2
section .text
intr%1entry:
    %2
    ; 保存上下文
    push ds
    push es
    push fs
    push gs
    pushad ;将通用寄存器压入栈中，

    mov al, 0x20 ; 写入EIO，发送中断结束标记
    out 0xa0, al ; 从片
    out 0x20, al ; 从片

    push %1 ; 压入中断向量号，
    call [idt_table + %1*4] ; 调用中断处理函数
    jmp intr_exit

section .data
    dd intr%1entry ;存储中断入口地址 形成数组intr_entry_table

%endmacro

section .text
global intr_exit
intr_exit:
;恢复上下文环境
    add esp, 4 ; 跳过中断号
    popad
    pop gs
    pop fs
    pop es
    pop ds
    add esp, 4 ; 跳过错误码
    iretd

;内部中断，不可屏蔽中断和异常
VECTOR 0x00, ZERO
VECTOR 0x01, ZERO
VECTOR 0x02, ZERO
VECTOR 0x03, ZERO
VECTOR 0x04, ZERO
VECTOR 0x05, ZERO
VECTOR 0x06, ZERO
VECTOR 0x07, ZERO
VECTOR 0x08, ZERO
VECTOR 0x09, ZERO
VECTOR 0x0a, ZERO
VECTOR 0x0b, ZERO
VECTOR 0x0c, ZERO
VECTOR 0x0d, ZERO
VECTOR 0x0e, ZERO
VECTOR 0x0f, ZERO
VECTOR 0x10, ZERO
VECTOR 0x11, ZERO
VECTOR 0x12, ZERO
VECTOR 0x13, ZERO

;Intel保留
VECTOR 0x14, ZERO
VECTOR 0x15, ZERO
VECTOR 0x16, ZERO
VECTOR 0x17, ZERO
VECTOR 0x18, ZERO
VECTOR 0x19, ZERO
VECTOR 0x1a, ZERO
VECTOR 0x1b, ZERO
VECTOR 0x1c, ZERO
VECTOR 0x1d, ZERO
VECTOR 0x1e, ERROR_CODE
VECTOR 0x1f, ZERO

;外部中断
VECTOR 0x20, ZERO ;时钟中断入口
VECTOR 0x21, ZERO ;键盘中断入口
VECTOR 0x22, ZERO ;级联用的
VECTOR 0x23, ZERO ;串口2对应入口
VECTOR 0x24, ZERO ;串口1对应入口
VECTOR 0x25, ZERO ;并口2对应入口
VECTOR 0x26, ZERO ;软盘对应入口
VECTOR 0x27, ZERO ;并口1对应入口
VECTOR 0x28, ZERO ;实时时钟对应入口
VECTOR 0x29, ZERO ;重定向
VECTOR 0x2a, ZERO ;保留
VECTOR 0x2b, ZERO ;保留
VECTOR 0x2c, ZERO ;ps/2鼠标
VECTOR 0x2d, ZERO ;fpu浮点单元
VECTOR 0x2e, ZERO ;硬盘
VECTOR 0x2f, ZERO ;保留

